﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
using System.Security.Cryptography;

namespace EasyChat
{
    public partial class login_frm : Form
    {
        /// <summary>
        /// IP地址
        /// </summary>
        private IPAddress _ipAddr;

        private static string readpublickey = "<RSAKeyValue><Modulus>0OLNSBeCcxsQ7gaPFUI6M36KWQ9PiRl2MF7tx3qw9YxWkvmy8pID7bjGf9vHEbYMv9D2K3pePTkeSGQ3pt4W0tocKiMFomb8fkoNUsVoS/+xBgsE0Le2FmoUnJBhBu7o7Mi+Ue0Fnr8NshcNVINSpNTSdnTapeEosmSfKhjetpE=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
        private static string readprivatekey = "<RSAKeyValue><Modulus>0OLNSBeCcxsQ7gaPFUI6M36KWQ9PiRl2MF7tx3qw9YxWkvmy8pID7bjGf9vHEbYMv9D2K3pePTkeSGQ3pt4W0tocKiMFomb8fkoNUsVoS/+xBgsE0Le2FmoUnJBhBu7o7Mi+Ue0Fnr8NshcNVINSpNTSdnTapeEosmSfKhjetpE=</Modulus><Exponent>AQAB</Exponent><P>9mqXKcmJF5RnSAM7GQTQf9L2RujyZb8Q4LgtSv11vhadwodJPXkGk0gir6P13aA91e4tue8k4dw10UZ8xUfNaw==</P><Q>2QKLicWhFr+VxsPOuZbm5ZrZT5IK7mUV9P9zXgJfk7NkuDlL0lbQyE/eIfSqQQ1aHuUO18kwAMoLgnGVRkiu8w==</Q><DP>YCVY09op3oRuBAAWt/1T6PwEUcikg6SYTkYujfr1TPUAGx20KwMk2KSlvAhqb04NsoIbX1f6+RF2AjDRkBwi/w==</DP><DQ>NnC+AsUSgXt0npWWsdZafHVZWO3hUicH2BuRnJ7pzUru1IyDKfRfkjD/H/OaFpG77w41qAqvwTLuqj3GXghz4w==</DQ><InverseQ>1dYl6cdguE1VgUX56eh6eTfGjXia5DcHRj9E6gd3ZjGcpW0PDX2dDFbkeR78fBVynuNgStfE6jaaqFXxPojkLA==</InverseQ><D>FnOKJOmB9+U82JiT4HER2F8Nd60Rm2bFMUXCwOILCxleZMW52iCfk3l8vFle+CRdEnDfRKUOY/4zpww+fwz33tgLH/12+kz8r4czcrvGCWLbPosgFTxqfxmvNNQVukNtAzoGv7n3ActK5xbUCF+Y7d1VjV9AXPw+APEUJZ2oftE=</D></RSAKeyValue>";
        private static RSACryptoServiceProvider crypt;
        byte[] bytes;

        string descode;//生成的8位随机des密钥，用于采用des的加解密

        #region 登录窗体构造函数

        /// <summary>
        /// 构造函数，自动生成
        /// </summary>
        public login_frm()
        {
            InitializeComponent();
        }

        #endregion

        #region 登录窗体的私有方法

        /// <summary>
        /// 验证登录信息
        /// </summary>
        /// <returns>验证结果</returns>
        private bool ValidateInfo()
        {
            if (user_tb.Text.Trim() == string.Empty)
            {
                MessageBox.Show("请填写用户名！",
                                "提示",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Information);
                user_tb.Focus();
                return false;
            }
            if (user_tb.Text[0] >= 48 && user_tb.Text[0]<=57)
            {
                MessageBox.Show("用户名不能以数字开头！",
                                "提示",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Information);
                user_tb.Focus();
                return false;
            }

            if (!IPAddress.TryParse(svrip_tb.Text, out _ipAddr))
            {
                MessageBox.Show("IP地址不合法!",
                                "提示",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Information);
                svrip_tb.Focus();
                return false;
            }
            int _port;
            if (!int.TryParse(svrport_tb.Text, out _port))
            {
                MessageBox.Show("端口号不合法!",
                                "提示",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Information);
                svrport_tb.Focus();
                return false;
            }
            else
            {
                if (_port < 1024 || _port > 65535)
                {
                    MessageBox.Show("端口号不合法!",
                                    "提示",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Information);
                    svrport_tb.Focus();
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 取消，关闭窗体
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cancel_btn_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        private byte[] RSA_Encode(string rsaencode)
        {

            try
            {

                crypt = new RSACryptoServiceProvider();
                UTF8Encoding enc = new UTF8Encoding();
                bytes = Encoding.UTF8.GetBytes(rsaencode);
                crypt.FromXmlString(readpublickey);
                bytes = crypt.Encrypt(bytes, false);
                string encryttext = enc.GetString(bytes);
                //textBox2.Text = "加密结果：\n" + encryttext + "\n";
                return bytes;
            }
            catch
            {
                Console.WriteLine("请检查是否打开公匙或者公匙是否损坏！");
                return bytes;
            }
        }

        private string RSA_Decode(byte[] rsadecode)
        {

            try
            {
                UTF8Encoding enc = new UTF8Encoding();
                byte[] decryptbyte;

                crypt.FromXmlString(readprivatekey);


                decryptbyte = crypt.Decrypt(rsadecode, false);
                string decrypttext = enc.GetString(decryptbyte);
                return decrypttext;
                //textBox3.Text = "解密结果：\n" + decrypttext + "\n";
            }
            catch
            {
                Console.WriteLine("请检查是否打开私匙或者私匙是否损坏！");
                return Encoding.UTF8.GetString(rsadecode);

            }
        }
        /// <summary>
        /// 生成随机字符串
        /// </summary>
        /// <param name="length">目标字符串的长度</param>
        /// <param name="useNum">是否包含数字，1=包含，默认为包含</param>
        /// <param name="useLow">是否包含小写字母，1=包含，默认为包含</param>
        /// <param name="useUpp">是否包含大写字母，1=包含，默认为包含</param>
        /// <param name="useSpe">是否包含特殊字符，1=包含，默认为不包含</param>
        /// <param name="custom">要包含的自定义字符，直接输入要包含的字符列表</param>
        /// <returns>指定长度的随机字符串</returns>
        public string GetRnd(int length, bool useNum, bool useLow, bool useUpp, bool useSpe, string custom)
        {
            byte[] b = new byte[4];
            new System.Security.Cryptography.RNGCryptoServiceProvider().GetBytes(b);
            Random r = new Random(BitConverter.ToInt32(b, 0));
            string s = null, str = custom;

            if (useNum == true) { str += "0123456789"; }
            if (useLow == true) { str += "abcdefghijklmnopqrstuvwxyz"; }
            if (useUpp == true) { str += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; }
            if (useSpe == true) { str += "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"; }

            for (int i = 0; i < length; i++)
            {
                s += str.Substring(r.Next(0, str.Length - 1), 1);
            }

            return s;
        }
        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void login_btn_Click(object sender, EventArgs e)
        {
            //验证数据合法性
            if (!ValidateInfo())
            {
                return;
            }
            int port = int.Parse(svrport_tb.Text);
            //向服务器发出连接请求
            TCPConnection conn = new TCPConnection(_ipAddr, port);
            TcpClient _tcpc = conn.Connect();
            if (_tcpc == null)
            {
                MessageBox.Show("无法连接到服务器，请重试！",
                                "错误",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Exclamation);
            }
            else
            {
                NetworkStream netstream = _tcpc.GetStream();//提供用于访问网络的基本数据流
                //向服务器发送用户名以确认身份
                netstream.Write(Encoding.Unicode.GetBytes(user_tb.Text), 0, Encoding.Unicode.GetBytes(user_tb.Text).Length);
                //得到登录结果
                byte[] buffer = new byte[50];
                byte[] sendbuffer = new byte[128];
                netstream.Read(buffer, 0, buffer.Length);//该方法将数据读入 buffer 参数并返回成功读取的字节数。如果没有可以读取的数据，则 Read 方法返回 0。
                string connResult = Encoding.Unicode.GetString(buffer).TrimEnd('\0');
                if (connResult.Equals("cmd::Failed"))
                {
                    MessageBox.Show("您的用户名已经被使用，请尝试其他用户名!",
                                    "提示",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Information);
                    return;
                }
                else
                {
                    
                    descode = GetRnd(8, true, true, true, true, "");
                    sendbuffer = RSA_Encode(descode);
                    netstream.Write(sendbuffer, 0, sendbuffer.Length);
                    //MessageBox.Show(RSA_Decode(sendbuffer));
                    string svrskt = svrip_tb.Text + ":" + svrport_tb.Text ;
                    chat_frm chatFrm = new chat_frm(user_tb.Text, netstream, svrskt,descode);//一个巧妙的参数传递方法
                    chatFrm.Owner = this;
                    //netstream.Write(RSA_Encode(GetRnd(8, true, true, true, true, "")), 0, RSA_Encode(GetRnd(8, true, true, true, true, "")).Length);

                    this.Hide();
                    chatFrm.Show();

                }
            }
        }

        /// <summary>
        /// 初始化登录信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void login_frm_Load(object sender, EventArgs e)
        {
            svrip_tb.Text = "192.168.12.103";
            svrport_tb.Text = "8888";
            user_tb.Focus();
        }

        #endregion
    }
}